options validvarname=upcase;
%let domain=adlb;
*** get data ;
%get_data(pre=sdtm,lib=sdtm,supp=y,lst=tv);
%get_data(pre=adam,lib=adam,lst=adsl);
%get_sdtm_se;

%*mk_param(lb,in=lb,out=lb,ord=  lbTESTCD  ,lib=work,fmt=3,debug=0,dropnd=0,use_cat_for_unit=0 );
%mk_param(lb,lib=sdtm,debug=1,dropnd=0);

%macro get_deci(dom=,lib=work,in=,id=&dom.testcd,var=&dom.stresc,debug=0);
%if %length(&lib)=0 %then %let lib=work;
%if %length(&debug)=0 %then %let debug=0;
%else %if &debug^=1 %then %let debug=0;
%let dsid=%sysfunc(open(&lib..&in));
%let chk1=%sysfunc(varnum(&dsid,&dom.cat));
%let chk2=%sysfunc(varnum(&dsid,&dom.scat));
%let dsid=%sysfunc(close(&dsid));
proc sql;
create table gd_val as
   select distinct %if &chk1>0 %then %do; &dom.cat, %end; %if &chk2>0 %then %do; &dom.scat, %end; &id,&var
   from &lib..&in where %ifnum(&var) and index(&var,".")
   order by %if &chk1>0 %then %do; &dom.cat, %end; %if &chk2>0 %then %do; &dom.scat, %end; &id;
create table gd_deci as
   select distinct %if &chk1>0 %then %do; &dom.cat, %end; %if &chk2>0 %then %do; &dom.scat, %end; &id,
   max(length(scan(&var,2,"."))) as deci
   from gd_val group by %if &chk1>0 %then %do; &dom.cat, %end; %if &chk2>0 %then %do; &dom.scat, %end; &id;
quit;
%if &debug=0 %then %do; %clrw(gd_val); %end;
%mend get_deci;

%get_deci(dom=lb,lib=sdtm,in=lb);
Proc freq data =_coded_lb(where = (visitnum = .));
   tables lbtestcd*visitnum*visit/ list missing nocum nopercent;
run;

proc sql noprint;
create table chk_lb as select distinct parcat1,lbcat,paramn,paramcd,lbtestcd,param,lbtest from _coded_lb;
quit;
proc sql;
select name into :adslvars separated by ",b." from dictionary.columns
   where upcase(memname)=upcase("adamadsl") and lowcase(name) ^in ("studyid" "usubjid" );
quit;
proc sql noprint;
create table info as select a.*,b.&adslvars,d1.lborres as baseo,d1.lbstresc as basec,deci,
   d1.lbstresn as base,d1.lbnrind as bnrind,e.visitdy as awtarget,e.visitnum as awvisitn,e.visit as awvisit,abs(sum(max(a.lbdy,0),max(0,-e.visitdy))) as awtdiff
   from _coded_lb as a left join adamadsl as b on a.usubjid=b.usubjid
   left join _coded_lb(where=(lowcase(lbblfl)="y")) as d1 on a.usubjid=d1.usubjid
      and a.lbtestcd=d1.lbtestcd and a.lbcat=d1.lbcat
  left join sdtmtv as e on int(a.visitnum)=e.visitnum
   left join gd_deci as gd on a.lbcat=gd.lbcat and a.lbtestcd=gd.lbtestcd
   where a.usubjid in (select usubjid from adamadsl)
   order by a.usubjid,a.lbtestcd,a.lbdtc,a.visitnum;
quit;
Proc freq data = _coded_lb;
   tables lbtestcd*lbtest*lbblfl/ list missing nocum nopercent;
run;
proc sql;
create table test0 as select distinct lbcat,lbtestcd,lbtest from info;
create table test1 as select distinct lbcat,lbtestcd,basec,lbstresc from info;
create table test2 as select distinct visitnum,visit %vchk(info,lbtpt,sql=y) %vchk(info,lbtptnum,sql=y)
   from info;
create table test3a as select * from info where missing(visitnum);
create table test3(where=(usubjid="TX-16-1093")) as select distinct a.usubjid,lbtestcd,a.visitnum,a.visit,lbdtc
   %vchk(info,lbtpt,sql=y) %vchk(info,lbtptnum,sql=y),exstdtc
   from info as a left join sdtm.ex as b on a.usubjid=b.usubjid and a.visit=b.visit;
create table test4(where=(usubjid="TX-16-1093")) as select distinct a.usubjid,lbtestcd,a.visitnum,a.visit,lbdtc
   %vchk(info,lbtpt,sql=y) %vchk(info,lbtptnum,sql=y),exstdtc
   from sdtm.lb as a left join sdtm.ex as b on a.usubjid=b.usubjid and a.visit=b.visit;
quit;
Proc freq data =info ;
   tables visitnum*visit*epoch/ list missing nocum nopercent;
run;

proc format;
   invalue  $ishift
   'LOW to LOW' = 11
   'LOW to NORMAL' = 12
   'LOW to HIGH' = 13
   'LOW to ABNORMAL' = 15
   'LOW to MISSING' = 14
   'NORMAL to LOW' = 21
   'NORMAL to NORMAL' = 22
   'NORMAL to HIGH' = 23
   'NORMAL to ABNORMAL' = 25
   'NORMAL to MISSING' = 24
   'HIGH to LOW' = 31
   'HIGH to NORMAL' = 32
   'HIGH to HIGH' = 33
   'HIGH to ABNORMAL' = 35
   'HIGH to MISSING' = 34
   'ABNORMAL to LOW' =51 
   'ABNORMAL to NORMAL' =52
   'ABNORMAL to HIGH' =53
   'ABNORMAL to ABNORMAL' =55 
   'ABNORMAL to MISSING' =54 
   'MISSING to LOW' = 41
   'MISSING to NORMAL' = 42
   'MISSING to HIGH' = 43
   'MISSING to ABNORMAL' = 45
   'MISSING to MISSING' = 44
   ;
quit;

Proc sort data =info;
   by usubjid lbtestcd lbdtc visitnum %vchk(info,lbtptnum) %vchk(info,lbrefid);
run;

data to01fl/*(drop=atm adtm)*/ miss;
   label
      studyid="Study Identifier"
      usubjid="Unique Subject Identifier"
      siteid="Study Site Identifier"
      age="Age"
      sex="Sex"
      race="Race"
      saffl="Safety Population Flag"
      /*trt01p="Planned Treatment for Period 01"
      trt01pn="Planned Treatment for Period 01 (N)"
      trt01a="Actual Treatment for Period 01"
      trt01an="Actual Treatment for Period 01 (N)"*/
      trtp="Planned Treatment"
      trtpn="Planned Treatment (N)"
      trta="Actual Treatment"
      trtan="Actual Treatment (N)"
      visit="Visit Name"
      visitnum="Visit Number"
      avisit="Analysis Visit"
      avisitn="Analysis Visit (N)"/*
      atptref="Analysis Timepoint Reference"
      atptn="Analysis Timepoint (N)"
      atpt="Analysis Timepoint"*/
      adt="Analysis Date"
      atm="Analysis Time"
      adtm="Analysis Datetime"
      ady="Analysis Relative Day"
      parcat1="Parameter Category 1"
      parcat1n="Parameter Category 1 (N)"
      paramn="Parameter (N)"
      paramcd="Parameter Code"
      param="Parameter"
      avalc="Analysis Value (C)"
      aval="Analysis Value"
      anrlo="Analysis Normal Range Lower Limit"
      anrhi="Analysis Normal Range Upper Limit"
      anrind="Analysis Reference Range Indicator"
      anrange="Analysis Normal Range"
      anrindcd="Analysis Reference Range Code"
      base="Baseline Value"
      basec="Baseline Value (C)"
      bnrind="Baseline Reference Range Indicator"
      bnrindc="Baseline Reference Range Indicator (C)"
      bnrindcd="Baseline Reference Range Code"
      chg="Change from Baseline"
      chgc="Change from Baseline (C)"
      pchg="Percent Change from Baseline"
      ablfl="Baseline Record Flag"
      nbdec="Decimal Precision Test"
      visityp="Type of Visit"
   ;
   length trtp visityp $100. anrindcd bnrindcd $1. avisit avalc anrindc bnrindc  $200.;
   set info;
   by usubjid lbtestcd lbdtc visitnum %vchk(info,lbtptnum) %vchk(info,lbrefid);

   *** treatment stuff ;
      if visit='Day 1' then do;
   trtp=trt01p;
   trta=trt01a;
   trtpn=trt01pn;
	trtan=trt01an;
end;
if visit='Day 2' then do;
   trtp=trt02p;
   trta=trt02a;
   trtpn=trt02pn;
	trtan=trt02an;
end;
if visit='Day 3' then do;
   trtp=trt03p;
   trta=trt03a;
   trtpn=trt03pn;
	trtan=trt03an;
end;
if visit='Day 4' then do;
   trtp=trt04p;
   trta=trt04a;
   trtpn=trt04pn;
	trtan=trt04an;
end;
if visit='Day 5' then do;
   trtp=trt05p;
   trta=trt05a;
   trtpn=trt05pn;
	trtan=trt05an;
end;
if visit='Day 6' then do;
   trtp=trt06p;
   trta=trt06a;
   trtpn=trt06pn;
	trtan=trt06an;
end;

   *** date & time stuff ;
   format adt yymmdd10.;
   format atm time5.;
   format adtm datetime13.;

   if ^missing(%rmtime(lbdtc)) then adt=input(%rmtime(lbdtc),is8601da.);
   if ^missing(%kptime(lbdtc)) then atm=input(%kptime(lbdtc),is8601tm.);
   if nmiss(adt,atm)=0 then adtm=input(%rmtime(lbdtc)||"%upcase(t)"||%kptime(lbdtc),e8601dt.);
   ady=lbdy;
   *aperady=adt-trtsdt+(trtsdt<=adt);

   if ^missing(visitnum) then avisitn=int(visitnum);
   else put "%upcase(%str(w)arning: missing visitnum for) " usubjid lbdtc= lbtestcd=;
   if avisitn ne . then AVISIT = strip(put(avisitn,visitn.));
   *avisit=strip(visit);

   if visitnum=int(visitnum) then visityp=propcase("scheduled");
   else visityp=propcase("unscheduled");

   *** values ;
   avalc=strip(lbstresc);
   aval=lbstresn;

   if missing(deci) then nbdec=0;
   else nbdec=deci;

   anrind=lbnrind;
   anrindcd=substr(upcase(anrind),1,1);
   bnrindcd=substr(upcase(bnrind),1,1);
   anrindc=upcase(anrind);
   bnrindc=upcase(bnrind);

   *** change from baseline ;
   if 2<avisitn then do;
      if n(aval,base)=2 then do;
         chg=aval-base;
         chgc=strip(put(chg,best.));
      end;
      if n(chg,base)=2 and base^=0 then pchg=(chg/base)*100;/*
      if anrind ne "" and bnrind ne "" then do; shift1 = catx(' to ', bnrind, anrind); shift1n = input(shift1, $ishift.); end;
      if anrind eq "" and bnrind ne "" then do; shift1 = catx(' to ', bnrind, "MISSING"); shift1n = input(shift1, $ishift.); end;
      if anrind ne "" and bnrind eq "" then do; shift1 = catx(' to ', "MISSING", anrind); shift1n = input(shift1, $ishift.); end;*/
   end;

   anrlo=lbstnrlo;
   anrhi=lbstnrhi;
   anrange=catx(" - ",ifc(missing(anrlo)," ",put(anrlo,best.)),ifc(missing(anrhi)," ",put(anrhi,best.)));
   if anrlo = .  and anrhi ne . then anrange = '<= ' || strip(put(anrhi,best.)); 
   else if anrlo ne . and anrhi = . then anrange = '>= ' || strip(put(anrlo,best.));
   *** baseline flag ;
   ablfl=lbblfl;

   if LBSTNRC ne " " and anrange=" " then anrange=strip(LBSTNRC);
   else if LBSTNRC ne " " and anrange ne " " then anrange=strip(anrange)||", "||strip(LBSTNRC);
   else anrange=strip(anrange);
/*coalesce(LBSTNRC,anrange);*/

   *** exclusion ;
   output to01fl;
   if missing(avalc) then output miss;
run;
proc sql;
create table chk_val as select distinct lbstresc,lbstresn,avalc,aval from to01fl;
quit;

data _tofl _miss;
   set to01fl;
   tavisitn = int(avisitn);
   if avalc ne "" then output _tofl;
   if avalc="" then output _miss;
run;

proc sort data=_tofl;
   by usubjid parcat1 paramn AVISITN lbdtc %vchk(info,atptn) %vchk(info,lbspid) awtdiff; 
run;
data _to00fl chk01fl(keep=usubjid parcat1 paramn paramcd adt avisitn visitnum %vchk(info,atptn) awtdiff %vchk(info,lbspid) anl01fl);
   label anl01fl="Analysis Record Flag 01";
   set _tofl;
   by usubjid parcat1 paramn AVISITN lbdtc  %vchk(info,atptn) %vchk(info,lbspid) awtdiff;
   if int(avisitn) < 2   then 
      do;
          if lowcase(arm)="not assigned" then do;if last.AVISITN then ANL01FL = 'Y'; end;
          else ANL01FL = ablfl;
      end;
   else 
      do;
         if first.AVISITN then ANL01FL = 'Y';
      end;

run;

data to00fl;
   set _to00fl _miss;
   run;
Proc freq data =to00fl ;
   tables usubjid*arm*visitnum/ list missing nocum nopercent;
run;
Proc sort data =to00fl out =param nodupkey ;
   by paramcd parcat1;
run;
Proc SQL;
   create table check as
   SELECT count(parcat1) as N, paramcd,parcat1,param,paramn
   FROM param
   group by paramcd
   ;
QUIT;
data paramcd;
   set check;
   if n gt 1 then do; paramcd=strip(paramcd)||First(parcat1);
                       param=strip(param)||"-"||strip(parcat1);
   end;
run;

data fin;
   label    SRCSEQ="Source Sequence Number"
            SHIFT1="Shift 1"
            SHIFT1N="Shift 1 (N)"
            APERIOD="Period"
            APERIODC="Period (C)";
   set to00fl;
   SRCSEQ=lbseq;
   
if index(visit, 'Day')>0 and upcase(visit) ^='DAY -1' then aperiod=input(strip(scan(visit, 2, '')), best.);
/*else if upcase(visit)='DAY -1' then Aperiod=1;*/
if aperiod ne . then aperiodc="Period 0"||strip(put(aperiod,best.));
else aperiodc=" ";

   if APeriod ne . then do;
 If BNRIND ne '' and ANRIND ne '' then SHIFT1=strip(BNRIND )||" to "||strip(ANRIND);
 If shift1='LOW to LOW' then shift1n =1;
If shift1='LOW to NORMAL' then shift1n= 2;
If shift1='LOW to HIGH' then shift1n = 3;
If shift1='NORMAL to LOW' then shift1n= 4;
If shift1='NORMAL to NORMAL' then shift1n= 5;
If shift1='NORMAL to HIGH' then shift1n= 6;
If shift1='HIGH to LOW' then shift1n= 7;
If shift1='HIGH to NORMAL' then shift1n= 8;
If shift1='HIGH to HIGH' then shift1n = 9;
end; 
   
run;
Proc freq data =fin ;
   tables paramn*paramcd*param/ list missing nocum nopercent;
run;

Proc sort data =fin out =fin2 nodup dupout=check ;
   by subjid;
run;
proc sql;
   create table adamw.adlb (label="Laboratory Analysis" sortedby=studyid usubjid parcat1 paramcd avisit visit adt atm) as
   select b.studyid,b.usubjid,b.subjid,/*b.lsubjid,*/b.siteid,b.armcd,b.actarmcd,
          b.randafl,b.randbfl, b.saffl,b.pkfl,b.pdfl,/*b.trt01p,b.trt01pn,b.trt01a,b.trt01an,*/TRTSDT,TRTSDTM,TRTEDT,TRTEDTM,
   trtp,trtpn,trta,trtan,/*aperiod, aperiodc,*/avisit,avisitn,adt,atm,adtm, ady,
   parcat1n,b.parcat1,b.paramn,p.paramcd,p.param,avalc,aval,anrlo,anrhi,anrind,anrange,
/*shift1,shift1n,*/
lbclsig,/*nbdec,*/chg,/*chgc,pchg,*/
   base,basec,bnrind,ablfl,srcseq,visit,visitnum,visityp,anl01fl
   from fin2 as b left join paramcd as p
   on b.paramn=p.paramn
   order studyid,usubjid,parcat1,paramcd,avisit,visit,adt,atm
   ;
quit;

proc sql;
create table chk_u as select distinct parcat1,paramcd,param,lborresu,lbstresu from fin;
create table chk00 as select usubjid,paramcd,avisit,adt/*,atm*/ from fin;
create table chk01 as select distinct usubjid,trtp,/*trt01p,*/avisit from fin;
create table chk02 as select distinct parcat1,paramn,paramcd,param,lbtest,lbstresu from fin;
create table chk03 as select lbstresn,lbornrlo,lbornrhi,lbstnrlo,anrange,shift1,shift1n from fin;
create table chk_pchg as select distinct usubjid,parcat1,paramn,paramcd,param,avisitn,avisit,adt,aval,base,chg,/*pchg,*/
   ablfl from fin /*where .<pchg<-100 or 100<pchg*/;
create table chk99 as select distinct a.usubjid,a.visitnum,a.visit,lbdtc,
   ifn(^missing(chg),1,.) as ischg,exstdtc
   from fin as a left join sdtm.ex as b on a.usubjid=b.usubjid and a.visit=b.visit;
create table chk_01fl as select distinct usubjid,parcat1,paramcd,avisit,adt,visit,anl01fl from fin;
quit;

%clrw;